# -*- coding:utf-8 -*-
from urllib import parse
import base64
from abc import ABCMeta, abstractmethod


class CTFCrypto(metaclass=ABCMeta):

    @abstractmethod
    def encode(self, text):
        raise NotImplementedError

    @abstractmethod
    def decode(self, text):
        raise NotImplementedError

    @abstractmethod
    def brute_force(self, text):
        raise NotImplementedError


# 16进制转换
class HexToString(CTFCrypto):

    def encode(self, text):
        ret = ''
        for c in text:
            ret += str(hex(ord(c)))[2:]
        return ret

    def decode(self, text):
        ret = ''
        for index in range(0, len(text), 2):
            ret += chr(int(text[index:index + 2], 16))
        return ret

    def brute_force(self, text):
        pass


# 栅栏密码
class Fence(CTFCrypto):
    key = 0

    def __init__(self, key):
        self.key = key

    def encode(self, text):
        ciphertext = ""
        temp = []
        for i in range(self.key):
            temp.append("")
        for index, i in enumerate(text):
            temp[index % self.key] += i
        # print("".join(temp))
        ciphertext = "".join(temp)
        return ciphertext

    def decode(self, text):
        plaintext = ""
        length = len(text)
        min_row = length // self.key
        max_num = length % self.key
        temp = []
        index = 0
        for i in range(self.key):
            if i < max_num:
                temp.append(text[index:index + min_row + 1])
                index += min_row + 1
            else:
                temp.append(text[index:index + min_row])
                index += min_row
        # print(temp)
        for i in range(length):
            plaintext += temp[i % self.key][i // self.key]
        return plaintext

    def brute_force(self, text):
        for i in range(len(text) - 1):
            print(self.decode(text, i + 1))


# 摩斯密码
class Morse(CTFCrypto):

    alphabet_to_morse = {
        "A": ".-",
        "B": "-...",
        "C": "-.-.",
        "D": "-..",
        "E": ".",
        "F": "..-.",
        "G": "--.",
        "H": "....",
        "I": "..",
        "J": ".---",
        "K": "-.-",
        "L": ".-..",
        "M": "--",
        "N": "-.",
        "O": "---",
        "P": ".--.",
        "Q": "--.-",
        "R": ".-.",
        "S": "...",
        "T": "-",
        "U": "..-",
        "V": "...-",
        "W": ".--",
        "X": "-..-",
        "Y": "-.--",
        "Z": "--..",
        "a": ".-",
        "b": "-...",
        "c": "-.-.",
        "d": "-..",
        "e": ".",
        "f": "..-.",
        "g": "--.",
        "h": "....",
        "Ii": "..",
        "j": ".---",
        "k": "-.-",
        "l": ".-..",
        "m": "--",
        "n": "-.",
        "o": "---",
        "p": ".--.",
        "q": "--.-",
        "r": ".-.",
        "s": "...",
        "t": "-",
        "u": "..-",
        "v": "...-",
        "w": ".--",
        "x": "-..-",
        "y": "-.--",
        "z": "--..",
        "0": "-----",
        "1": ".----",
        "2": "..---",
        "3": "...--",
        "4": "....-",
        "5": ".....",
        "6": "-....",
        "7": "--...",
        "8": "---..",
        "9": "----.",
        "Ä": ".-.-",
        "Ü": "..--",
        "ß": "...--..",
        "À": ".--.-",
        "È": ".-..-",
        "É": "..-..",
        ".": ".-.-.-",
        ",": "--..--",
        ":": "---...",
        ";": "-.-.-.",
        "?": "..--..",
        "-": "-....-",
        "_": "..--.-",
        "(": "-.--.",
        ")": "-.--.-",
        "'": ".----.",
        "=": "-...-",
        "+": ".-.-.",
        "/": "-..-.",
        "@": ".--.-.",
        "Ñ": "--.--",
        "&": "． ．．．",
        "$": "．．．━ ．．━",
        "/": "━ ．．━ ．",
        "\"": "．━ ．．━ ．",
        " ": " ",
        "": ""
    }

    morse_to_alphabet = dict()

    def __init__(self):
        for item in self.alphabet_to_morse:
            self.morse_to_alphabet[self.alphabet_to_morse[item]] = item

    def encode(self, text):
        ret = ''
        for item in text:
            ret += self.alphabet_to_morse.get(item) + '/'
        return ret

    def decode(self, text):
        ret = ''
        letters = text.split("/")
        for item in letters:
            ret += self.morse_to_alphabet.get(item)
        return ret

    def brute_force(self, text):
        pass


# url编码
class UrlDecode(CTFCrypto):

    def encode(self, text):
        return parse.quote(text)

    def decode(self, text):
        return parse.unquote(text)

    def brute_force(self, text):
        pass


# Base编码
class Base(CTFCrypto):
    num = 0

    def __init__(self, num):
        self.num = num

    def decode(self, text):
        if 16 == self.num:
            self.base16decode(text)
        elif 32 == self.num:
            self.base32decode(text)
        elif 64 == self.num:
            self.base64decode(text)

    def encode(self, text):
        if 16 == self.num:
            self.base16encode(text)
        elif 32 == self.num:
            self.base32encode(text)
        elif 64 == self.num:
            self.base64encode(text)

    @staticmethod
    def base16encode(text):
        return base64.b16encode(text)

    @staticmethod
    def base16decode(text):
        return base64.b16decode(text)

    @staticmethod
    def base32encode(text):
        return base64.b32encode(text)

    @staticmethod
    def base32decode(text):
        return base64.b32decode(text)

    @staticmethod
    def base64encode(text):
        return base64.b64encode(text)

    @staticmethod
    def base64decode(text):
        return base64.b64decode(text)

    def brute_force(self, text):
        pass


# 云影密码
class CloudShadow(CTFCrypto):
    lower = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u',
             'v', 'w', 'x', 'y', 'z']
    uppercase = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
                 'U', 'V', 'W', 'X', 'Y', 'Z']

    def decode(self, text):
        dic = [chr(i) for i in range(ord("A"), ord("Z") + 1)]
        flag = []
        c2 = [i for i in text.split("0")]
        for i in c2:
            c3 = 0
            for j in i:
                c3 += int(j)
            flag.append(dic[c3 - 1])
        return "".join(flag)[:-1]

    def encode(self, text):
        dic = [chr(i) for i in range(ord("A"), ord("Z") + 1)]
        m = [i for i in text]
        tmp = []
        flag = []
        for i in range(len(m)):
            for j in range(len(dic)):
                if m[i] == dic[j]:
                    tmp.append(j + 1)
        for i in tmp:
            res = ""
            if i >= 8:
                res += int(i / 8) * "8"
            if i % 8 >= 4:
                res += int(i % 8 / 4) * "4"
            if i % 4 >= 2:
                res += int(i % 4 / 2) * "2"
            if i % 2 >= 1:
                res += int(i % 2 / 1) * "1"
            flag.append(res + "0")
        return "".join(flag)[:-1]

    def brute_force(self, text):
        pass


# 凯撒密码
class Caesar(CTFCrypto):
    key = 0

    def __init__(self, key):
        self.key = key

    def encode(self, text):
        r = ""
        for i in text:
            r += chr((ord(i) + self.key) % 128)
        return r

    def decode(self, text):
        r = ""
        for i in text:
            r += chr((ord(i) - self.key) % 128)
        return r

    def brute_force(self, text):
        result = []
        for k in range(128):
            tmp = self.decode(text)
            result.append(tmp)
        return result


class Baconian(CTFCrypto):

    def decode(self, text):
        pass

    def encode(self, text):
        pass

    def brute_force(self, text):
        pass
